home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / BARNET / UTILITIES / BASCAT / bascat / mdwopt.h < prev   
C/C++ Source or Header  |  1996-02-23  |  13KB  |  322 lines

  1. /*
  2.  * mdwopt.h
  3.  *
  4.  * Options parsing, similar to GNU getopt_long
  5.  */
  6.  
  7. /*----- Notices -----------------------------------------------------------*
  8.  *
  9.  * This program comes with no warranty, not even of any kind, unless
  10.  * someone other than the author offers to provide one.  It may be used
  11.  * and distributed under the terms of the GNU General Public Licence, in
  12.  * the interests of promoting freely available software for Linux.
  13.  */
  14.  
  15. #ifndef MDWOPT_H
  16. #define MDWOPT_H
  17.  
  18. /*----- Options handling structures ---------------------------------------*/
  19.  
  20. /* --- mdwopt_data --- *
  21.  *
  22.  * Contains all the information needed by the mdwopt routine to do its work.
  23.  */
  24.  
  25. typedef struct
  26. {
  27.   /* --- Public variables --- */
  28.  
  29.   char *arg;                /* Arg of current option, or 0 */
  30.   int opt;                /* Value of current option */
  31.   int ind;                /* 0 for init, index when done */
  32.   int err;                /* Set nonzero for error messages */
  33.   char *prog;                /* Program name (from argv[0]) */
  34.  
  35.   /* --- Private variables --- *
  36.    *
  37.    * Don't play with these, please.
  38.    */
  39.  
  40.   char *list;                /* Current short options pointer */
  41.   int next;                /* Next argument, unpermuted */
  42.   int order;                /* Ordering of options, flags */
  43.   char *env;                /* Where we are in the env var */
  44.   char *estart;                /* Pointer to env var buffer */
  45. }
  46. mdwopt_data;
  47.  
  48. /*----- Global variables --------------------------------------------------*/
  49.  
  50. extern mdwopt_data mdwopt_global;    /* The default global data */
  51.  
  52. /* --- For compatibility with older programs (and prettiness) --- *
  53.  *
  54.  * The macros here access the global structure defined above.  I consider it
  55.  * to be perfectly acceptable to use these macros in new code, because it
  56.  * looks nicer than playing with mdwopt_global.
  57.  */
  58.  
  59. #define optarg (mdwopt_global.arg)    /* Argument of current option */
  60. #define optopt (mdwopt_global.opt)    /* Code of current option */
  61. #define opterr (mdwopt_global.err)    /* Zero to report error messages */
  62. #define optind (mdwopt_global.ind)    /* Index of first non-option */
  63. #define optprog (mdwopt_global.prog)    /* Pointer to program name */
  64.  
  65. /*----- Type definitions --------------------------------------------------*/
  66.  
  67. /* --- Long options definition table --- */
  68.  
  69. struct option
  70. {
  71.   const char *name;            /* Name of the long option */
  72.   int has_arg;                /* Does it have an argument? */
  73.   int *flag;                /* Address of flag variable */
  74.   int val;                /* Value to store/return */
  75. };
  76.  
  77. /* --- Old-style names for argument flags in long options table --- */
  78.  
  79. enum
  80. {
  81.   no_argument,                /* No argument required */
  82.   required_argument,            /* User must specify argument */
  83.   optional_argument            /* Argument is optional */
  84. };
  85.  
  86. /* --- New style flag names --- */
  87.  
  88. enum
  89. {
  90.   gFlag_argReq=1,            /* Required argument */
  91.   gFlag_argOpt=2,            /* Optional argument */
  92.   gFlag_switch=4,            /* OR val into flag, don't store */
  93.   gFlag_negate=8,            /* Allow long option to be negated */
  94.   gFlag__last_long_opt_flag=0        /* Dummy value */
  95. };
  96.  
  97. enum
  98. {
  99.   gFlag_noLongs=1,            /* Don't read long options */
  100.   gFlag_noShorts=2,            /* Don't read short options */
  101.   gFlag_numbers=4,            /* Read numeric options */
  102.   gFlag_negation=8,            /* Allow `+' for negations */
  103.   gFlag_envVar=16,            /* Parse options from env var */
  104.   gFlag__last_mdwopt_flag=0        /* Dummy value */
  105. };
  106.  
  107. enum
  108. {
  109.   gFlag_negated=256,            /* Option flag was negated by user */
  110.   gFlag__last_return_flag=0        /* Dummy value */
  111. };
  112.  
  113. /*----- Main code ---------------------------------------------------------*/
  114.  
  115. /* --- mdwopt --- *
  116.  *
  117.  * Arguments:    int argc == number of command line arguments
  118.  *        char * const *argv == pointer to command line arguments
  119.  *        const char *shortopt == pointer to short options information
  120.  *        const struct option *longopts == pointer to long opts info
  121.  *        int *longind == where to store matched longopt
  122.  *        mdwopt_data *data == persistent state for the parser
  123.  *        int flags == various useful flags
  124.  *
  125.  * Returns:    Value of option found next, or an error character, or
  126.  *        EOF for the last thing.
  127.  *
  128.  * Use:
  129.  
  130.  *        Reads options.  The routine should be more-or-less compatible
  131.  *        with standard getopts, although it provides many more
  132.  *        features even than the standard GNU implementation.
  133.  *
  134.  *        The precise manner of options parsing is determined by
  135.  *        various flag settings, which are described below.  By setting
  136.  *        flag values appropriately, you can achieve behaviour very
  137.  *        similar to most other getopt routines.
  138.  *
  139.  *
  140.  *        How options parsing appears to users
  141.  *
  142.  *        A command line consists of a number of `words' (which may
  143.  *        contain spaces, according to various shell quoting
  144.  *        conventions).  A word may be an option, an argument to an
  145.  *        option, or a non-option.  An option begins with a special
  146.  *        character, usually `-', although `+' is also used sometimes.
  147.  *        As special exceptions, the word containing only a `-' is
  148.  *        considered to be a non-option, since it usually represents
  149.  *        standard input or output as a filename, and the word
  150.  *        containing a double-dash `--' is used to mark all following
  151.  *        words as being non-options regardless of their initial
  152.  *        character.
  153.  *
  154.  *        Traditionally, all words after the first non-option have been
  155.  *        considered to be non-options automatically, so that options
  156.  *        must be specified before filenames.  However, this
  157.  *        implementation can extract all the options from the command
  158.  *        line regardless of their position.  This can usually be
  159.  *        disabled by setting one of the environment variables
  160.  *        `POSIXLY_CORRECT' or `_POSIX_OPTION_ORDER'.
  161.  *
  162.  *        There are two different styles of options: `short' and
  163.  *        `long'.
  164.  *
  165.  *        Short options are the sort which Unix has known for ages: an
  166.  *        option is a single letter, preceded by a `-'.  Short options
  167.  *        can be joined together to save space (and possibly to make
  168.  *        silly words): e.g., instead of giving options `-x -y', a user
  169.  *        could write `-xy'.  Some short options can have arguments,
  170.  *        which appear after the option letter, either immediately
  171.  *        following, or in the next `word' (so an option with an
  172.  *        argument could be written as `-o foo' or as `-ofoo').  Note
  173.  *        that options with optional arguments must be written in the
  174.  *        second style.
  175.  *
  176.  *        When a short option controls a flag setting, it is sometimes
  177.  *        possible to explicitly turn the flag off, as well as turning
  178.  *        it on, (usually to override default options).  This is
  179.  *        usually done by using a `+' instead of a `-' to introduce the
  180.  *        option.
  181.  *
  182.  *        Long options, as popularised by the GNU utilities, are given
  183.  *        long-ish memorable names, preceded by a double-dash `--'.
  184.  *        Since their names are more than a single character, long
  185.  *        options can't be combined in the same way as short options.
  186.  *        Arguments to long options may be given either in the same
  187.  *        `word', separated from the option name by an equals sign,
  188.  *        or in the following `word'.
  189.  *
  190.  *        Long option names can be abbreviated if necessary, as long
  191.  *        as the abbreviation is unique.  This means that options can
  192.  *        have sensible and memorable names but still not require much
  193.  *        typing from an experienced user.
  194.  *
  195.  *        Like short options, long options can control flag settings.
  196.  *        The options to manipulate these settings come in pairs: an
  197.  *        option of the form `--set-flag' might set the flag, while an
  198.  *        option of the form `--no-set-flag' might clear it.
  199.  *
  200.  *        It is usual for applications to provide both short and long
  201.  *        options with identical behaviour.  Some applications with
  202.  *        lots of options may only provide long options (although they
  203.  *        will often be only two or three characters long).  In this
  204.  *        case, long options can be preceded with a single `-'
  205.  *        character, and negated by a `+' character.
  206.  *
  207.  *        Finally, some (older) programs accept arguments of the form
  208.  *        `-<number>', to set some numerical parameter, typically a
  209.  *        line count of some kind.
  210.  *
  211.  *
  212.  *        How programs parse options
  213.  *
  214.  *        An application parses its options by calling mdwopt
  215.  *        repeatedly.  Each time it is called, mdwopt returns a value
  216.  *        describing the option just read, and stores information about
  217.  *        the option in a data block.  The value -1 is returned when
  218.  *        there are no more options to be read.  The `?' character is
  219.  *        returned when an error is encountered.
  220.  *
  221.  *        Before starting to parse options, the value data->ind must be
  222.  *        set to 0 or 1.  The value of data->err can also be set, to
  223.  *        choose whether errors are reported by mdwopt.
  224.  *
  225.  *        The program's `argc' and `argv' arguments are passed to the
  226.  *        options parser, so that it can read the command line.  A
  227.  *        flags word is also passed, allowing the program fine control
  228.  *        over parsing.  The flags are described above.
  229.  *
  230.  *        Short options are described by a string, which once upon a
  231.  *        time just contained the permitted option characters.  Now the
  232.  *        options string begins with a collection of flag characters,
  233.  *        and various flag characters can be put after options
  234.  *        characters to change their properties.
  235.  *
  236.  *        If the first character of the short options string is `+',
  237.  *        `-' or `!', the order in which options are read is modified,
  238.  *        as follows:
  239.  *
  240.  *        `+' forces the POSIX order to be used.  As soon as a non-
  241.  *            option is found, mdwopt returns -1.
  242.  *
  243.  *        `-' makes mdwopt treat non-options as being `special' sorts
  244.  *            of option.  When a non-option word is found, the value 0
  245.  *            is returned, and the actual text of the word is stored as
  246.  *            being the option's argument.
  247.  *
  248.  *        `!' forces the default order to be used.  The entire command
  249.  *            line is scanned for options, which are returned in order.
  250.  *            However, during this process, the options are moved in
  251.  *            the `argv' array, so that they appear before the non-
  252.  *            options.
  253.  *
  254.  *        A `:' character may be placed after the ordering flag (or at
  255.  *        the very beginning if no ordering flag is given) which
  256.  *        indicates that the character `:', rather than `?', should be
  257.  *        returned if a missing argument error is detected.
  258.  *
  259.  *        Each option in the string can be followed by a `+' sign,
  260.  *        indicating that it can be negated, a `:' sign indicating that
  261.  *        it requires an argument, or a `::' string, indicating an
  262.  *        optional argument.  Both `+' and `:' or `::' may be given,
  263.  *        although the `+' must come first.
  264.  *
  265.  *        If an option is found, the option character is returned to
  266.  *        the caller.  A pointer to an argument is stored in data->arg,
  267.  *        or NULL is stored if there was no argument.  If a negated
  268.  *        option was found, the option character is returned ORred with
  269.  *        gFlag_negated (bit 8 set).
  270.  *
  271.  *        Long options are described in a table.  Each entry in the
  272.  *        table is of type `struct option', and the table is terminated
  273.  *        by an entry whose `name' field is null.  Each option has
  274.  *        a flags word which, due to historical reasons, is called
  275.  *        `has_arg'.  This describes various properties of the option,
  276.  *        such as what sort of argument it takes, and whether it can
  277.  *        be negated.
  278.  *
  279.  *        When mdwopt finds a long option, it looks the name up in the
  280.  *        table.  The index of the matching entry is stored in the
  281.  *        `longind' variable, passed to mdwopt (unless `longind' is 0):
  282.  *        a value of -1 indicates that no long option was found.  The
  283.  *        behaviour is then dependent on the values in the table entry.
  284.  *        If `flag' is nonzero, it points to an integer to be modified
  285.  *        by mdwopt.  Usually the value in the `val' field is simply
  286.  *        stored in the `flag' variable.  If the flag gFlag_switch is
  287.  *        set, however, the value is combined with the existing value
  288.  *        of the flags using a bitwise OR.  If gFlag_negate is set,
  289.  *        then the flag bit will be cleared if a matching negated long
  290.  *        option is found.  The value 0 is returned.
  291.  *
  292.  *        If `flag' is zero, the value in `val' is returned by mdwopt,
  293.  *        possibly with bit 8 set if the option was negated.
  294.  *
  295.  *        Arguments for long options are stored in data->arg, as
  296.  *        before.
  297.  *
  298.  *        Numeric options, if enabled, cause the value `#' to be
  299.  *        returned, and the numeric value to be stored in data->opt.
  300.  *
  301.  *        If the flag gFlag_envVar is set on entry, options will be
  302.  *        extracted from an environment variable whose name is built by
  303.  *        capitalising all the letters of the program's name.  (This
  304.  *        allows a user to have different default settings for a
  305.  *        program, by calling it through different symbolic links.)
  306.  */
  307.  
  308. int mdwopt(int argc,char * const *argv,
  309.        const char *shortopt,
  310.        const struct option *longopts,int *longind,
  311.        mdwopt_data *data,int flags);
  312.  
  313. /* --- Macros for more commonly used routines --- */
  314.  
  315. #define getopt(c,v,o) mdwopt(c,v,o,0,0,0,gFlag_noLongs)
  316. #define getopt_long(c,v,o,l,li) mdwopt(c,v,o,l,li,0,0)
  317. #define getopt_long_only(c,v,o,l,li) mdwopt(c,v,o,l,li,0,gFlag_noShorts)
  318.  
  319. /*----- That's all, folks -------------------------------------------------*/
  320.  
  321. #endif
  322.